package cn.edu.gzgs.service.impl;

import cn.edu.gzgs.dto.AuditContentDTO;
import cn.edu.gzgs.dto.AuditPageQueryDTO;
import cn.edu.gzgs.dto.AuditRecordDTO;
import cn.edu.gzgs.entity.AuditContent;
import cn.edu.gzgs.entity.AuditRecord;
import cn.edu.gzgs.entity.SupportingML;
import cn.edu.gzgs.enums.AuditResultStatus;
import cn.edu.gzgs.enums.AuditStatus;
import cn.edu.gzgs.exception.BusinessException;
import cn.edu.gzgs.mapper.AuditMapper;
import cn.edu.gzgs.mapper.SupportingMLMapper;
import cn.edu.gzgs.mapper.UserMapper;
import cn.edu.gzgs.entity.User;
import cn.edu.gzgs.service.AuditService;
import cn.edu.gzgs.service.WebSocketMessageService;
import cn.edu.gzgs.util.AliOssUtil;
import cn.edu.gzgs.vo.AuditContentVO;
import cn.edu.gzgs.vo.WebOfficeVO;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
@RequiredArgsConstructor
public class AuditServiceImpl extends ServiceImpl<AuditMapper,AuditContent > implements AuditService {


    private final AuditMapper auditMapper;

    private final SupportingMLMapper supportingMLMapper;

    private final UserMapper userMapper;

    private final AliOssUtil aliOssUtil;

    private final WebSocketMessageService webSocketMessageService;

    /**
     * 审核内容新增
     * @param auditContentDTO
     */
    @Override
    @Transactional
    public void auditWithsupportingMLAdd(AuditContentDTO auditContentDTO) {
        //检查是否有重复上传
        AuditContent checkAuditContent = auditMapper.selectByCheck(auditContentDTO);
        if(checkAuditContent!=null){
            throw new BusinessException("请勿重复上传,如需修改往修改接口");
        }

        // 将DTO转换成实体
        AuditContent auditContent = new AuditContent();
        BeanUtil.copyProperties(auditContentDTO, auditContent);
        // 判断字段是否为空
        if (auditContent.getWorkload() == null){
            throw new BusinessException("请填写申报工作量");
        } else if (auditContent.getSystemId() ==null || auditContent.getProjectId() ==null || auditContent.getListMetaId() ==null) {
            throw new BusinessException("项目树层级出错，请注意系统ID、项目ID、元项目清单ID");
        }

        // 设置各个审核状态
        auditContent.setAuditStatus(AuditStatus.WAITING_FOR_AUDIT);
        auditContent.setResultStatus(AuditResultStatus.WAITING_FOR_AUDIT);


        // 插入审核内容（此方法为MybatisPlus的方法）
        try {
            auditMapper.insert(auditContent);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        Long auditContentId = auditContent.getId();

        //向佐证材料表插入n条数据
        List<SupportingML> supportingMLList=auditContentDTO.getSupportingMLList();
        if(supportingMLList!=null && supportingMLList.size()>0){
            //批量插入
            supportingMLList.forEach(supportingML -> {
                supportingML.setAuditContentId(auditContentId);
            });
            supportingMLMapper.insertBatch(supportingMLList);
        }else{
            throw new BusinessException("文件未上传，请上传文件");
        }
    }



    /**
     * 修改审核内容
     * @param auditContentDTO
     */
    @Override
    @Transactional
    public void update(AuditContentDTO auditContentDTO) {
        AuditContent newAuditContent = auditMapper.selectById(auditContentDTO.getId());
        if(newAuditContent.getAuditStatus()== AuditStatus.AUDITING){
            throw new BusinessException("审核中，请勿修改");
        } else if (newAuditContent.getResultStatus()== AuditResultStatus.AUDIT_PASS) {
            throw new BusinessException("审核已通过，请勿修改");
        }
        // 将DTO转换成实体
        AuditContent auditContent = new AuditContent();
        BeanUtil.copyProperties(auditContentDTO, auditContent);
        // 查询原来的佐证材料
        List<SupportingML> willDeleteSupportingMLList=supportingMLMapper.getListByAuditContentId(auditContent.getId());

        // 修改审核内容
        auditMapper.updateById(auditContent);
        Long auditContentId = auditContent.getId();

        //获取出现上传的佐证材料
        List<SupportingML> supportingMLList=auditContentDTO.getSupportingMLList();

        //向佐证材料表插入n条数据
        if(supportingMLList!=null && supportingMLList.size()>0){
            //批量插入
            supportingMLList.forEach(supportingML -> {
                supportingML.setAuditContentId(auditContentId);
            });
            supportingMLMapper.insertBatch(supportingMLList);
        }else{
            throw new BusinessException("文件未上传，请上传文件");
        }

        //事务完成,开始删除原来的OSS佐证材料
        if(willDeleteSupportingMLList!=null && willDeleteSupportingMLList.size()>0){
            //批量删除
            willDeleteSupportingMLList.forEach(supportingML -> {
                //获取连接
                String url = supportingML.getSupportingMaterial();
                //抽取文件名
                String objectName = url.substring(url.lastIndexOf('/') + 1);
                try {
                    aliOssUtil.delete(objectName);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            });
        }
        //删除数据库原有的佐证材料
        supportingMLMapper.deleteBatchIds(willDeleteSupportingMLList);

    }

    /**
     * 审核
     * @param auditRecordDTO
     */
    @Override
    @Transactional
    public void audit(AuditRecordDTO auditRecordDTO) {
        AuditContent auditingContent = auditMapper.selectById(auditRecordDTO.getId());
        if (auditingContent.getAuditStatus()==AuditStatus.AUDIT_RESULT ||
                auditingContent.getAuditStatus()==AuditStatus.AUDITING ||
                auditingContent.getResultStatus()==AuditResultStatus.AUDIT_PASS){
            throw new BusinessException("审核状态出错");
        }
        // 切换审核状态
        AuditContent auditContent = new AuditContent();
        auditContent.setId(auditRecordDTO.getId());
        auditContent.setAuditStatus(AuditStatus.AUDITING);
        auditMapper.updateById(auditContent);

        // 修改审核结果
        auditContent.setAuditStatus(AuditStatus.AUDIT_RESULT);
        auditContent.setResultStatus(auditRecordDTO.getResultStatus());
        if (auditRecordDTO.getFeedbackInfo()==null){
            auditContent.setFeedbackInfo("无审核意见");
        }else{
            auditContent.setFeedbackInfo(auditRecordDTO.getFeedbackInfo());
        }
        auditMapper.updateById(auditContent);

        //添加审核记录
        AuditRecord auditRecord = new AuditRecord();
        auditRecord.setAuditContentId(auditingContent.getId());
        auditRecord.setAuditTeacherId(auditRecordDTO.getAuditTeacherId());
        auditRecord.setLatestAuditTeacherId(auditRecordDTO.getAuditTeacherId());
        auditRecord.setApplicantTeacherId(auditingContent.getSubmitterId());
        log.info("添加审核记录：{}", auditRecord);
        auditMapper.insertAuditRecord(auditRecord);

        // 审核完成后发送消息给申请人
        String applicantId = String.valueOf(auditingContent.getSubmitterId());
        String projectName = "工作量申报";
        String feedbackContent = auditRecordDTO.getFeedbackInfo();
        
        // 获取审核老师信息作为发送者
        String auditTeacherId = String.valueOf(auditRecordDTO.getAuditTeacherId());
        String auditTeacherName = "系统通知"; // 默认值
        
        if (auditRecordDTO.getAuditTeacherId() != null) {
            User auditTeacher = userMapper.selectById(auditRecordDTO.getAuditTeacherId());
            if (auditTeacher != null) {
                auditTeacherName = auditTeacher.getName();
            }
        }
        
        if (auditRecordDTO.getResultStatus() == AuditResultStatus.AUDIT_PASS) {
            // 审核通过
            webSocketMessageService.sendProjectPassNotification(applicantId, projectName, auditTeacherId, auditTeacherName);
            log.info("已发送审核通过通知给用户: {}, 审核老师: {}", applicantId, auditTeacherName);
        } else if (auditRecordDTO.getResultStatus() == AuditResultStatus.AUDIT_FAIL) {
            // 审核不通过
            String reason = (feedbackContent != null && !feedbackContent.trim().isEmpty()) 
                ? feedbackContent : "";
            webSocketMessageService.sendProjectRepulseNotification(applicantId, projectName, reason, auditTeacherId, auditTeacherName);
            log.info("已发送审核不通过通知给用户: {}, 审核老师: {}, 原因: {}", applicantId, auditTeacherName, reason);
        }
    }


    /**
     * 获取佐证材料的签名URL，用于在线查看
     *
     * @param supportingMaterialId 佐证材料ID
     * @param expireInSeconds URL有效期，单位秒
     * @return 签名URL
     */
    @Override
    public WebOfficeVO getSupportingMaterialSignedUrl(Long supportingMaterialId, long expireInSeconds) throws Exception {
        // 查询佐证材料
        SupportingML supportingML = supportingMLMapper.selectById(supportingMaterialId);
        if (supportingML == null) {
            throw new BusinessException("佐证材料不存在");
        }
        
        // 获取文件URL
        String url = supportingML.getSupportingMaterial();
        // 从URL中提取文件名
        String objectName = url.substring(url.lastIndexOf('/') + 1);
        
        try {
            // 对URL编码的文件名进行解码
            objectName = java.net.URLDecoder.decode(objectName, "UTF-8");
            log.info("解码后的文件名: {}", objectName);
        } catch (Exception e) {
            log.error("URL解码失败: {}", e.getMessage());
        }
        
        // 生成签名URL，设置为在线预览模式
        return aliOssUtil.generateWebOfficePreviewUrl(objectName);
    }
    
    /**
     * 下载佐证材料
     *
     * @param supportingMaterialId 佐证材料ID
     * @return 文件下载URL
     */
    @Override
    public String downloadSupportingMaterial(Long supportingMaterialId) throws Exception {
        // 查询佐证材料
        SupportingML supportingML = supportingMLMapper.selectById(supportingMaterialId);
        if (supportingML == null) {
            throw new BusinessException("佐证材料不存在");
        }
        
        // 获取文件URL
        String url = supportingML.getSupportingMaterial();
        // 从URL中提取文件名
        String objectName = url.substring(url.lastIndexOf('/') + 1);
        
        try {
            // 对URL编码的文件名进行解码
            objectName = java.net.URLDecoder.decode(objectName, "UTF-8");
            log.info("下载文件 - 解码后的文件名: {}", objectName);
        } catch (Exception e) {
            log.error("下载文件 - URL解码失败: {}", e.getMessage());
        }
        
        // 生成签名URL，下载链接有效期设置为1小时，明确设置为下载模式
        return aliOssUtil.generatePresignedDownloadUrl(objectName, 3600);
    }

    /**
     * 驳回审核
     * @param id
     */
    @Override
    public void dismissAudit(Long id) {
        AuditContent auditContent = new AuditContent();
        auditContent.setId(id);
        auditContent.setAuditStatus(AuditStatus.WAITING_FOR_AUDIT);
        auditContent.setResultStatus(AuditResultStatus.WAITING_FOR_AUDIT);
        auditContent.setFeedbackInfo("驳回审核");
        auditMapper.updateById(auditContent);
    }

    @Override
    public PageDTO<AuditContentDTO> dynamicQueries(AuditPageQueryDTO auditPageQueryDTO) {
        String projectId = auditPageQueryDTO.getProjectId();
        String listMetaId = auditPageQueryDTO.getListMetaId();
        String systemId = auditPageQueryDTO.getSystemId();
        Long submitterId = auditPageQueryDTO.getSubmitterId();
        AuditStatus auditStatus = auditPageQueryDTO.getAuditStatus();
        AuditResultStatus resultStatus = auditPageQueryDTO.getResultStatus();

        // 创建分页对象
        Page<AuditContent> page = new Page<>(auditPageQueryDTO.getPage(), auditPageQueryDTO.getPageSize());

        // 构建查询条件并执行分页查询
        Page<AuditContent> result = this.lambdaQuery()
                .eq(StrUtil.isNotBlank(projectId), AuditContent::getProjectId, projectId)
                .eq(StrUtil.isNotBlank(listMetaId), AuditContent::getListMetaId, listMetaId)
                .eq(StrUtil.isNotBlank(systemId), AuditContent::getSystemId, systemId)
                .eq(submitterId != null, AuditContent::getSubmitterId, submitterId)
                .eq(auditStatus != null, AuditContent::getAuditStatus, auditStatus)
                .eq(resultStatus != null, AuditContent::getResultStatus, resultStatus)
                .orderByDesc(AuditContent::getCreatedTime)
                .page(page);

        // 转换为DTO对象并查询佐证材料和提交人信息
        List<AuditContentDTO> dtoList = result.getRecords().stream()
                .map(auditContent -> {
                    AuditContentDTO dto = new AuditContentDTO();
                    BeanUtils.copyProperties(auditContent, dto);

                    // 查询提交人姓名
                    if (auditContent.getSubmitterId() != null) {
                        User submitter = userMapper.selectById(auditContent.getSubmitterId());
                        if (submitter != null) {
                            dto.setSubmitterName(submitter.getName());
                        }
                    }

                    // 查询该审核内容对应的佐证材料列表
                    List<SupportingML> supportingMLList = supportingMLMapper.selectList(
                            new LambdaQueryWrapper<SupportingML>()
                                    .eq(SupportingML::getAuditContentId, auditContent.getId())
                                    .orderByAsc(SupportingML::getCreatedTime)
                    );
                    dto.setSupportingMLList(supportingMLList);

                    return dto;
                })
                .collect(Collectors.toList());

        // 封装并返回分页结果
        PageDTO<AuditContentDTO> pageDTO = new PageDTO<>();
        pageDTO.setRecords(dtoList);
        pageDTO.setTotal(result.getTotal());
        pageDTO.setCurrent(result.getCurrent());
        if (result.getSize()!=0){
            pageDTO.setSize(result.getSize());
        }else{
            pageDTO.setSize(1);
        }
        if (result.getPages()!=0){
            pageDTO.setPages(result.getPages());
        }else{
            pageDTO.setPages(10);
        }
        return pageDTO;
    }

    /**
     * 撤销审核
     * @param id
     */
    @Override
    @Transactional
    public void revokeAudit(Long id) {
        AuditContent auditContent = auditMapper.selectById(id);
        if (auditContent == null){
            throw new BusinessException("审核内容不存在");
        }else if (auditContent.getAuditStatus()!=AuditStatus.WAITING_FOR_AUDIT || auditContent.getResultStatus()!=AuditResultStatus.WAITING_FOR_AUDIT){
            throw new BusinessException("审核内容状态错误");
        }

        auditMapper.deleteBatchContentIds(id);



        // 查询原来的佐证材料
        List<SupportingML> willDeleteSupportingMLList=supportingMLMapper.getListByAuditContentId(id);



        //事务完成,开始删除原来的OSS佐证材料
        if(willDeleteSupportingMLList!=null && willDeleteSupportingMLList.size()>0){
            //批量删除
            willDeleteSupportingMLList.forEach(supportingML -> {
                //获取连接
                String url = supportingML.getSupportingMaterial();
                //抽取文件名
                String objectName = url.substring(url.lastIndexOf('/') + 1);
                try {
                    aliOssUtil.delete(objectName);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            });

            //删除数据库原有的佐证材料
            supportingMLMapper.deleteBatchIds(willDeleteSupportingMLList);

            // 删除审核内容
            auditMapper.deleteById(id);
        }

    }

}
